;; Mode: LISP; Syntax: Common-lisp; Package: aklemme
;; Names: Ardell Klemme, Bruce Ho, Jimmy Cumming         Date: 11/05/12
;; Course: ICS 313   Assignment: 6
;; File: repl.lisp

;;;=========================R-E-P-L=======================;;;

; AK: custom read-eval-print-loop                                                    
; AK: recursively calls repl unless user exits with 'quit command.                  
(defun game-repl ()
    (let ((cmd (game-read)))
        (unless (eq (car cmd) 'quit)
            (game-print (game-eval cmd))
            (game-repl))))

; AK: custom read function takes string arguments and adds parenthesis around it
;     and adds quote for function command.
(defun game-read ()
    (let ((cmd (read-from-string (concatenate 'string "(" (read-line) ")"))))
         ; AK: function adds quote to data portion of command string
         (flet ((quote-it (x)
                    (list 'quote x)))
             (cons (car cmd) (mapcar #'quote-it (cdr cmd))))))

; AK: defines available input from user such that users cannot "hack" the game.
(defparameter *allowed-commands* '(look walk pickup inventory help h actions choose))

; AK: limits available input from user
(defun game-eval (sexp)
    (if (member (car sexp) *allowed-commands*)
        (eval sexp)
        '(i do not know that command.)))

; AK: capitalize first letter of each sentence
(defun tweak-text (lst caps lit)
  (when lst
    (let ((item (car lst))
          (rest (cdr lst)))
      (cond ((eql item #\space) (cons item (tweak-text rest caps lit)))
            ((member item '(#\! #\? #\.)) (cons item (tweak-text rest t lit)))
            ((eql item #\") (tweak-text rest caps (not lit)))
            (lit (cons item (tweak-text rest nil lit)))
            (caps (cons (char-upcase item) (tweak-text rest nil lit)))
            (t (cons (char-downcase item) (tweak-text rest nil nil)))))))

; AK: custom print function to handle output from interface.                        
(defun game-print (lst)
    (princ (coerce (tweak-text (coerce (string-trim "() "
                                                     (prin1-to-string lst))
                                       'list)
                               t nil)
                   'string))
    (fresh-line))